package com.briup.bookstore.service.impl;

import com.briup.bookstore.common.exception.ServiceException;
import com.briup.bookstore.common.response.ResultCode;
import com.briup.bookstore.common.security.SecurityContext;
import com.briup.bookstore.domain.bean.Book;
import com.briup.bookstore.domain.vo.BookDetailVO;
import com.briup.bookstore.domain.vo.BookVO;
import com.briup.bookstore.mapper.BookMapper;
import com.briup.bookstore.service.BookService;
import com.briup.bookstore.utils.BeanUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 图书服务实现类
 */
@Service
@RequiredArgsConstructor
public class BookServiceImpl implements BookService {

    private final BookMapper bookMapper;


    @Override
    public List<BookVO> showBooks() {
        // 从数据库中查询所有已经上架的图书
        List<Book> books = bookMapper.queryAllEnabled();

        // 模拟挑选出最畅销的20本图书
        // 随机打乱图书列表
        Collections.shuffle(books);
        // 获取前20本图书
        List<Book> top20Books = books.stream().limit(20).toList();

        // 将查询到的图书列表转换为图书VO列表
        return BeanUtil.convertList(top20Books, BookVO.class);
    }

    @Override
    public List<BookVO> findByCategory(Integer categoryId) {
        List<Book> books = bookMapper.queryByCategoryId(categoryId);
        return BeanUtil.convertList(books, BookVO.class);
    }

    @Override
    public List<BookVO> searchBook(String query) {
        List<Book> books = bookMapper.searchBook(query);
        return BeanUtil.convertList(books, BookVO.class);
    }

    @Override
    public BookDetailVO findById(Integer id) {
        // 获取当前登录用户的id
        Integer userId = SecurityContext.userId();
        // 从数据库中查询图书详情
        return bookMapper.queryByIdWithUserId(id, userId);
    }

    @Override
    // 只要在方法上添加了@Transactional注解，那么就会被Spring框架自动管理事务
    @Transactional
    public void updateStock(Map<Integer, Integer> map) {
        // 获取所有需要修改库存的图书id
        Set<Integer> bookIds = map.keySet();
        // 根据图书id查询图书列表
        List<Book> books = bookMapper.queryByIds(bookIds);
        // 遍历图书列表，检查是否存在库存不足的图书，如果存在，那么抛出异常
        books.forEach(book -> {
            // 获取当前图书的库存数量
            Integer storeNum = book.getStoreNum();
            // 获取当前图书需要修改的库存数量
            Integer updateNum = map.get(book.getId());
            if (updateNum < 0) {
                // 如果当前图书需要修改的库存数量为负数，
                // 那么表示当前操作为新增订单，需要检查是否存在库存不足的情况
                if (storeNum + updateNum < 0) {
                    throw new ServiceException(ResultCode.BOOK_STORE_NOT_ENOUGH);
                }
            } else if (updateNum == 0) {
                // 如果当前图书需要修改的库存数量为0，
                // 说明当前操作无论是新增订单还是删除订单，都是一条异常数据
                throw new ServiceException(ResultCode.ORDER_ERROR);
            }
            // 如果库存充足，那么就更新图书库存数量
            map.put(book.getId(), storeNum + updateNum);
        });
        // 批量更新图书库存数量
        map.forEach(bookMapper::updateStock);
    }
}
